package com.lzj.demo.mybatis.plus;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzj.demo.dto.Student;
import com.lzj.demo.mapper.StudentMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

//mybatis官网:https://baomidou.com/
@Slf4j
@Service("aStudentService")
public class AStudentServiceImpl extends ServiceImpl<StudentMapper,Student> implements AStudentService {
    //lambdaQuery().eq(Entity::getId, value).one();
    //lambdaUpdate().eq(Entity::getId, value).update();

    @Override
    public void test() {
        //链式调用 lambda 式
         List<Student> students = lambdaQuery()
                 //.select(Student::getId,Student::getAge,Student::getName)
                 //.select(i -> i.getProperty().startsWith("test"))
                 //.select(i-> Objects.nonNull(i.getProperty()))
                 .eq(Student::getId,1L)//等于 id = 1

                 //区间范围
                 .ne(Student::getName,"凯哥")//不等于  name <> '凯哥'
                 .gt(Student::getAge,18)//大于 age > 18
                 .lt(Student::getAge,30)//小于 age < 30
                 .ge(Student::getAge,18)//大于等于 age >= 18
                 .le(Student::getAge,30)//小于等于 age <= 30
                 .between(Student::getAge,18,30)//age between 18 and 30
                 .notBetween(Student::getAge,18,30)//age not between 18 and 30

                 //模糊匹配
                 .like(Student::getName,"凯")//模糊匹配  name not like '%凯%'
                 .notLike(Student::getName,"Faker")//name not like '%Faker%'
                 .likeLeft(Student::getName,"a")//LIKE '%a'
                 .likeRight(Student::getName,"a")//LIKE 'a%'

                 //是否为空
                 .isNull(Student::getName)//name is null
                 .isNotNull(Student::getName)//name is not null

                 //指定集合
                 .in(Student::getAge, Arrays.asList(1,2,3))//age in (1,2,3)
                 .notIn(Student::getAge,Arrays.asList(1,2,3))//age not in (1,2,3)

                 //嵌套sql
                 .inSql(Student::getId,"select id from table where id < 3") //id in (select id from table where id < 3)
                 .notInSql(Student::getId, "select id from table where id < 3") //id not in (select id from table where id < 3)

                 //分组
                 //.groupBy(Student::getId, Student::getAge) //group by id,name

                 //排序
                 .orderByDesc(Student::getId)
                 .orderByAsc(Student::getName)
                 //.orderBy(true, true, Student::getId, Student::getName)//order by id ASC,name AS

                 //
                 .having("sum(age) > {0}", 11)

                 //func 方法(主要方便在出现if...else下调用不同方法能不断链)
                 .func(i -> {
                     if (condition(1L)) {
                         i.eq(Student::getId, 1L);
                     } else {
                         i.ne(Student::getAge, 1L);
                     }
                 })

                 //拼接or
                 .or().eq(Student::getName,"b")//or name = 'b'
                 //or嵌套
                 .or(i->i.eq(Student::getName,"b").ge(Student::getAge,18))// or (name = 'b' and age > 18)
                 //and嵌套
                 .and(i -> i.eq(Student::getName, "c").ne(Student::getAge, 18))// and (name = 'c' and age <> 18)
                 //nested 正常嵌套 不带 AND 或者 OR
                 .nested(i->i.eq(Student::getName,"d").ne(Student::getAge,18))// (name = 'd' and age <> 18)

                 //拼接 sql
                 .apply("id = 1")
                 .apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")//date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
                 //该方法可用于数据库函数,动态入参的params对应前面applySql内部的{index}部分.这样是不会有sql注入风险的,反之会有!
                 .apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")//date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")

                 .exists("select id from student where age = 1")

                 .notExists("select id from student where age = 1")

                 //最后部分sql拼接:只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用
                 .last("limit 1")//无视规则直接sql最后拼接
                 .list();

         lambdaUpdate()
                 .setSql("name = 'b',age = 18")
                 .set(Student::getName,null)
                 .eq(Student::getId,1L)
                 .update();

    }

    private boolean condition(Long id){
        if(id == 1){
            return false;
        }
        return true;
    }
}
